package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.FineClueCompanyModel;
import com.xbongbong.paas.model.FineClueUserModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.service.CallCenterCommonService;
import com.xbongbong.crm.service.SearchCustomerService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.IModel;
import com.xbongbong.pro.customercommunicate.pojo.dto.DynamicDTO;
import com.xbongbong.pro.domain.entity.FineClueCompanyEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.FineClueEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.UpdateCustomerTeamScenesEnum;
import com.xbongbong.pro.enums.menu.enums.FineClueFormEnum;
import com.xbongbong.saas.domain.entity.RuleClueEntity;
import com.xbongbong.saas.domain.entity.RuleCustomerEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.paas.service.dynamic.help.DynamicDetailsHelper;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.service.EventChangeCustomerService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserDepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 钉钉回调变更客户
 * @author youli.chen
 * @version v1.0
 * @date 2019/2/19 18:55
 * @since v1.0
 */
@Service("eventChangeCustomerService")
public class EventChangeCustomerServiceImpl implements EventChangeCustomerService {

    private static final Logger LOG = LoggerFactory.getLogger(EventChangeCustomerServiceImpl.class);

    @Resource
    private UserModel userModel;
    @Resource
    private CallCenterCommonService callCenterCommonService;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private SearchCustomerService searchCustomerService;
    @Resource
    private UserDepartmentModel userDepartmentModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private FineClueUserModel fineClueUserModel;
    @Resource
    private FineClueCompanyModel fineClueCompanyModel;
    @Resource
    private ContactModel contactModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private DynamicDetailsHelper dynamicDetailsHelper;

    /**
     * 收到员工离职信息后的处理
     * 对应 org_user_leave
     * 将用户del置为1
     *
     * @param accessToken
     * @param corpId
     * @param userIds
     */
    @Async(value = "eventReceivePool")
    @Override
    public void orgUserLeave(String accessToken, String corpId, String userIds) throws XbbException {
        List<String> userIdList = JSON.parseArray(userIds, String.class);
        orgUserLeave(corpId,userIdList);
    }

    @Override
    public void orgUserLeave(String corpId, List<String> userIdList) throws XbbException {
        final List<UserEntity> userEntityList = new ArrayList<>();
        for ( String userId : userIdList ) {
            UserEntity user = userModel.getByKeyIngoreDel(userId, corpId);
            if ( user != null ) {
                //离职将用户置为删除
                LOG.info("orgUserLeave----离职将用户置为删除");
                user.setDel(1);
                userModel.update(user);

                userDepartmentModel.deleteByUserId(userId, corpId);

                // 清除离职话务中心角色
                LOG.info("orgUserLeave---- callCenter:开始清除所有话务中心角色");
                callCenterCommonService.removeCallCenterPosition(corpId, userId);
                // 清除离职搜客角色
                searchCustomerService.removeSoukePosition(corpId, userId);
                /*
                 * 思路：1.如果该公司开通了搜客，把坐席表离职人员解绑->把坐席表离职人员那条数据userId置为空，坐席关闭（同关闭坐席）
                 *      2.如果该公司只开通了工商查询，坐席表不做处理(坐席表里只有一条记录)
                 * */
                FineClueCompanyEntity fineClueCompanyEntity = fineClueCompanyModel.getByCorpid(corpId, FineClueEnum.FINE_CLUE.getType());
                if (Objects.nonNull(fineClueCompanyEntity)){
                    String userid = "";
                    //把userId置为""
                    fineClueUserModel.batchUpdateStaff(corpId, Arrays.asList(userId), FineClueFormEnum.STAFFCLOSE.getCode(),userid);
                }
//                fineClueUserModel.removeLeaveStaff(corpId,Arrays.asList(userId));
                userEntityList.add(user);
            }
        }
        if ( CollectionsUtil.isEmpty(userEntityList) ) {
            return;
        }
        try {
            // 员工离职逻辑
            LOG.info("员工{}离职，将其客户及相关资源退回公海池", userEntityList);
            returnLeaveUserCustomer2Public(corpId, userEntityList);
        } catch (Exception e) {
            LOG.error("员工离职，将其客户及相关资源退回公海池时出错", e);
        }

        try {
            // 员工离职逻辑
            returnLeaveUserClue2Public(corpId, userEntityList);
        } catch (Exception e) {
            LOG.error("员工离职，将其线索及相关资源退回公海池时出错", e);
        }

        try {
            recordContactDynamic4LeaveUser(corpId, userEntityList);
        } catch (Exception e) {
            LOG.error("员工离职，联系人退出团队动态记录失败", e);
        }

        try {
            recordContractDynamic4LeaveUser(corpId, userEntityList);
        } catch (Exception e) {
            LOG.error("员工离职，合同退出团队动态记录失败", e);
        }

        try {
            recordOpportunityDynamic4LeaveUser(corpId, userEntityList);
        } catch (Exception e) {
            LOG.error("员工离职，机会退出团队动态记录失败", e);
        }
    }

    private void recordOpportunityDynamic4LeaveUser(String corpId, List<UserEntity> userList) {
        recordDynamic4LeaveUser(corpId, userList, XbbRefTypeEnum.SALES_OPPORTUNITY, opportunityModel, ProjectLogEnum.OPPORTUNITY_UPDATE);
    }

    private void recordContractDynamic4LeaveUser(String corpId, List<UserEntity> userList) {
        recordDynamic4LeaveUser(corpId, userList, XbbRefTypeEnum.CONTRACT, contractModel, ProjectLogEnum.CONTRACT_UPDATE);
    }

    private void recordContactDynamic4LeaveUser(String corpId, List<UserEntity> userList) {
        recordDynamic4LeaveUser(corpId, userList, XbbRefTypeEnum.CONTACT, contactModel, ProjectLogEnum.CONTACT_UPDATE);
    }

    private void recordDynamic4LeaveUser(String corpId, List<UserEntity> userList, XbbRefTypeEnum xbbRefTypeEnum, IModel<? extends PaasFormDataEntityExt> iModel,ProjectLogEnum projectLogEnum){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        PaasMenuEntity paasMenuEntity = paasMenuModel.getByAlias4Distributor(xbbRefTypeEnum.getAlias(), corpId, DistributorMarkEnum.OTHER.getCode());
        if (Objects.isNull(paasMenuEntity)) {
            paasMenuEntity = new PaasMenuEntity();
        }
        String userIdInParam;
        switch (xbbRefTypeEnum) {
            case CONTACT:
                userIdInParam = "userIdContactIn";
                break;
            case CONTRACT:
                userIdInParam = "userIdContractIn";
                break;
            case SALES_OPPORTUNITY:
                userIdInParam = "userIdOpportunityIn";
                break;
            default:
                return;
        }
        for (UserEntity user : userList) {
            if (user != null && !StringUtil.isEmpty(user.getUserId())) {
                String userId = user.getUserId();
                String userName = user.getName();
                // 查询出每个离职用户所有的负责联系人总数
                List<String> userIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                userIdIn.add(userId);
                param.put("corpid", corpId);
                param.put("flowStatusIn", Arrays.asList(0, 2));
                param.put(userIdInParam, userIdIn);
                param.put("menuId", paasMenuEntity.getId());
                Integer entitysCount = iModel.getEntitysCount(param);

                // 模拟分页进行处理
                Integer start = 0;
                //每次查询1000条
                Integer pageNum = 1000;
                param.put("pageNum", pageNum);
                for (; start <= entitysCount; start = start + pageNum) {
                    param.put("start", start);
                    List<? extends PaasFormDataEntityExt> entitysWithoutSub = iModel.findEntitysWithoutSub(param);
                    List<DynamicDTO> dynamicDTOS = new ArrayList<>(entitysWithoutSub.size());
                    for (PaasFormDataEntityExt entityExt : entitysWithoutSub) {
                        DynamicDTO dynamicDTO = dynamicDetailsHelper.initDynamicDTO(user.getUserId(), CrmLogMemoConstant.DYNAMIC_USER_BACK_EXIT_TEAM_LEAVE, projectLogEnum.getSubType(),
                                DynamicDTO.initMemoHolder(userName), null, null, entityExt.getDataId());
                        dynamicDTOS.add(dynamicDTO);
                    }
                    dynamicDetailsHelper.insertDynamic(dynamicDTOS, corpId);
                }
            }
        }
    }

    /**
     * 将离职员工的客户的数据丢到公海池去
     * @param corpid
     * @param userList
     */
    private void returnLeaveUserCustomer2Public(String corpid, List<UserEntity> userList) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 获取menuId，用来移除经销商数据
        PaasMenuEntity paasMenuEntity = paasMenuModel.getByAlias4Distributor(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getAlias(), corpid, DistributorMarkEnum.OTHER.getCode());

        for(UserEntity user : userList) {
            if(user != null && !StringUtil.isEmpty(user.getUserId())) {
                String userId = user.getUserId();
                String userName = user.getName();
                param.clear();
                // 查询出每个离职用户所有的负责客户总数
                List<String> userIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                userIdIn.add(userId);
                param.put("corpid", corpid);
                param.put("flowStatusIn", Arrays.asList(0,2));
                param.put("userIdCustomerIn", userIdIn);
                Integer customerEntityExtCount = customerModel.getEntitysCount(param);

                // 模拟分页进行处理
                Integer pageNum = 1;
                //每次查询1000条
                Integer pageSize = 1000;
                Integer selectCount = pageSize;
                while (selectCount == pageSize) {
                    param.clear();
                    List<RuleCustomerEntity> customerExts = customerModel.getMainCustomerListByUserId(corpid, userId,
                            null, pageNum, pageSize, null, null, null, paasMenuEntity.getId());
                    selectCount = customerExts.size();
                    pageNum++;
                    List<Long> customerIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    List<String> customerNameIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for(RuleCustomerEntity entityExt : customerExts){
                        customerIdIn.add(entityExt.getId());
//                        JSONObject data = entityExt.getData();
//                        String customerName = FastJsonHelper.getStringOrDefaultFromFormData(data, CustomerManagementEnum.NAME.getAttr(), "");
                        String customerName = entityExt.getName();
                        customerNameIn.add(customerName);
                    }
                    Map<Long, List<Long>> formCustomerMap = customerExts.stream().collect(Collectors.toMap(RuleCustomerEntity::getFormId, v -> Collections.singletonList(v.getId()), (v1, v2) -> {
                        List<Long> result = new ArrayList<>(v1);
                        result.addAll(v2);
                        return result;
                    }));
                    LOG.info("步骤0formCustomerMap{}",formCustomerMap);
                    //更新团队操作，按表单分类来批量操作，继承规则是表单级
                    for (Map.Entry<Long, List<Long>> entry : formCustomerMap.entrySet()) {
                        LOG.info("步骤1customerIdList{}",entry.getValue());
                        userTeamService.updateCustomerTeam(user,entry.getValue(),UpdateCustomerTeamScenesEnum.USER_LEAVE,entry.getKey(),SaasMarkEnum.SAAS.getCode(),XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),DistributorMarkEnum.OTHER.getCode(),null);
                    }

                    // 记录日志
                    String logMemo = StringUtils.join(customerNameIn, "，");
                    if(customerIdIn.size() > 1){
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_LEAVE_CUSTOMER), userName, customerIdIn.size());
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(CustomerManagementEnum.NAME.getAttrName());
                        infoArrPojo.setContent(logMemo);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER,
                                OperateTypeEnum.RETURN_TO_PUBLIC, "", "", memo, "");
                    } else if(Objects.equals(customerIdIn.size(), 1)){
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_LEAVE_CUSTOMER), userName, logMemo);
                        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.RETURN_TO_PUBLIC,
                                customerIdIn.get(0).toString(), logMemo, memo, "");
                    }

                }
                LOG.info("用户 "+ user.getName() + "已离职，相关的客户处理完毕");
            }
        }
    }

    /**
     * 将离职员工的线索的数据丢到公海池去
     * @param corpid
     * @param userList
     */
    private void returnLeaveUserClue2Public(String corpid, List<UserEntity> userList) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for(UserEntity user : userList) {
            if(user != null && !StringUtil.isEmpty(user.getUserId())) {
                String userId = user.getUserId();
                String userName = user.getName();
                param.clear();
                // 查询出每个离职用户所有的负责线索总数
                List<String> userIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                userIdIn.add(userId);
                param.put("corpid", corpid);
                param.put("flowStatusIn", Arrays.asList(0,2));
                param.put("userIdClueIn", userIdIn);
                Integer clueEntityExtCount = clueModel.getEntitysCount(param);

                // 模拟分页进行处理
                Integer pageNum = 1;
                //每次查询1000条
                Integer pageSize = 1000;
                Integer selectCount = pageSize;
                while (selectCount == pageSize) {
                    param.clear();
                    List<RuleClueEntity> clueExts = clueModel.getMainClueListByUserId(corpid, userId,
                            null, pageNum, pageSize, null, null, null);
                    selectCount = clueExts.size();
                    pageNum++;
                    List<Long> clueIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    List<String> clueNameIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for(RuleClueEntity entityExt : clueExts){
                        clueIdIn.add(entityExt.getId());
                        clueNameIn.add(entityExt.getName());
                    }

                    Map<Long, List<Long>> formClueMap = clueExts.stream().collect(Collectors.toMap(RuleClueEntity::getFormId, v -> Collections.singletonList(v.getId()), (v1, v2) -> {
                        List<Long> result = new ArrayList<>(v1);
                        result.addAll(v2);
                        return result;
                    }));
                    //更新团队操作，按表单分类来批量操作，继承规则是表单级
                    for (Map.Entry<Long, List<Long>> entry : formClueMap.entrySet()) {
                        userTeamService.updateClueTeam(user,entry.getValue(),UpdateCustomerTeamScenesEnum.USER_LEAVE,entry.getKey(),SaasMarkEnum.SAAS.getCode(),XbbRefTypeEnum.CLUE.getCode(),DistributorMarkEnum.OTHER.getCode(),null);
                    }

                    // 记录日志
                    String logMemo = StringUtils.join(clueNameIn, "，");
                    if(clueIdIn.size() > 1){
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_LEAVE_CLUE), userName, clueIdIn.size());
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(ClueEnum.COMPANY_NAME.getAttrName());
                        infoArrPojo.setContent(logMemo);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CLUE,
                                OperateTypeEnum.RETURN_TO_PUBLIC, "", "", memo, "");
                    } else if(Objects.equals(clueIdIn.size(), 1)){
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_LEAVE_CLUE), userName, logMemo);
                        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.CLUE, OperateTypeEnum.RETURN_TO_PUBLIC,
                                clueIdIn.get(0).toString(), logMemo, memo, "");
                    }

                }
                LOG.info("用户 "+ user.getName() + "已离职，相关的线索处理完毕");
            }
        }
    }
}
